package com.ruoyi.system.controller;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.OjProblem;
import com.ruoyi.system.domain.OjSubmission;
import com.ruoyi.system.service.IOjPracticeService;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * OJ在线练习Controller
 * 
 * @author ruoyi
 * @date 2025-01-21
 */
@RestController
@RequestMapping("/system/oj")
public class OjPracticeController extends BaseController
{
    @Autowired
    private IOjPracticeService ojPracticeService;

    /**
     * 获取OJ题目列表
     */
    @PreAuthorize("@ss.hasPermi('system:oj:problems:query')")
    @GetMapping("/problems")
    public TableDataInfo listProblems(
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam(value = "difficulty", required = false) String difficulty,
            @RequestParam(value = "category", required = false) String category,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        startPage();
        List<OjProblem> list = ojPracticeService.selectProblemList(keyword, difficulty, category, status);
        return getDataTable(list);
    }

    /**
     * 根据ID获取OJ题目
     */
    @PreAuthorize("@ss.hasPermi('system:oj:problems:query')")
    @GetMapping("/problems/{problemId}")
    public AjaxResult getProblem(@PathVariable String problemId) {
        return success(ojPracticeService.selectProblemById(problemId));
    }

    /**
     * 新增OJ题目
     */
    @PreAuthorize("@ss.hasPermi('system:oj:problems:add')")
    @Log(title = "OJ题目管理", businessType = BusinessType.INSERT)
    @PostMapping("/problems")
    public AjaxResult addProblem(@RequestBody OjProblem ojProblem) {
        return toAjax(ojPracticeService.insertProblem(ojProblem));
    }

    /**
     * 修改OJ题目
     */
    @PreAuthorize("@ss.hasPermi('system:oj:problems:edit')")
    @Log(title = "OJ题目管理", businessType = BusinessType.UPDATE)
    @PutMapping("/problems")
    public AjaxResult editProblem(@RequestBody OjProblem ojProblem) {
        return toAjax(ojPracticeService.updateProblem(ojProblem));
    }

    /**
     * 删除OJ题目
     */
    @PreAuthorize("@ss.hasPermi('system:oj:problems:remove')")
    @Log(title = "OJ题目管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/problems/{problemIds}")
    public AjaxResult removeProblems(@PathVariable String[] problemIds) {
        return toAjax(ojPracticeService.deleteProblemByProblemIds(String.join(",", problemIds)));
    }



    /**
     * 获取题目测试用例
     */
    @PreAuthorize("@ss.hasPermi('system:oj:problems')")
    @GetMapping("/problems/{problemId}/testcases")
    public AjaxResult getProblemTestCases(@PathVariable String problemId)
    {
        try {
            List<Map<String, Object>> testCases = ojPracticeService.getProblemTestCases(problemId);
            return success(testCases);
        } catch (Exception e) {
            return error("获取测试用例失败：" + e.getMessage());
        }
    }

    /**
     * 运行代码（本地测试）
     */
    @PreAuthorize("@ss.hasPermi('system:oj:run')")
    @PostMapping("/run")
    public AjaxResult runCode(@RequestBody Map<String, Object> requestData)
    {
        try {
            String problemId = (String) requestData.get("problemId");
            String code = (String) requestData.get("code");
            String language = (String) requestData.get("language");
            String input = (String) requestData.get("input");
            Boolean enableO2 = (Boolean) requestData.get("enableO2");
            
            // 调用服务运行代码
            Map<String, Object> result = ojPracticeService.runCode(problemId, code, language, input, enableO2);
            
            return success(result);
        } catch (Exception e) {
            return error("代码运行失败：" + e.getMessage());
        }
    }

    /**
     * 提交代码
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submit')")
    @PostMapping("/submit")
    public AjaxResult submitCode(@RequestBody Map<String, Object> requestData)
    {
        try {
            String problemId = (String) requestData.get("problemId");
            String code = (String) requestData.get("code");
            String language = (String) requestData.get("language");
            Boolean enableO2 = (Boolean) requestData.get("enableO2");
            String submissionType = (String) requestData.get("submissionType");
            
            // 调用服务提交代码
            String submissionId = ojPracticeService.submitCode(problemId, code, language, enableO2, submissionType);
            
            Map<String, Object> result = new HashMap<>();
            result.put("submissionId", submissionId);
            result.put("message", "代码提交成功，正在评测中...");
            
            return success(result);
        } catch (Exception e) {
            return error("代码提交失败：" + e.getMessage());
        }
    }

    /**
     * 获取提交结果
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submissions')")
    @GetMapping("/submissions/{submissionId}/result")
    public AjaxResult getSubmissionResult(@PathVariable String submissionId)
    {
        try {
            Map<String, Object> result = ojPracticeService.getSubmissionResult(submissionId);
            return success(result);
        } catch (Exception e) {
            return error("获取提交结果失败：" + e.getMessage());
        }
    }

    /**
     * 获取OJ代码提交列表
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submissions:query')")
    @GetMapping("/submissions")
    public TableDataInfo listSubmissions(
            @RequestParam(value = "userId", required = false) String userId,
            @RequestParam(value = "problemId", required = false) String problemId,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "language", required = false) String language,
            @RequestParam(value = "startTime", required = false) String startTime,
            @RequestParam(value = "endTime", required = false) String endTime,
            @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        startPage();
        List<OjSubmission> list = ojPracticeService.selectSubmissionList(userId, problemId, status, language, startTime, endTime);
        return getDataTable(list);
    }

    /**
     * 根据ID获取OJ代码提交
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submissions:query')")
    @GetMapping("/submissions/{submissionId}")
    public AjaxResult getSubmission(@PathVariable String submissionId) {
        return success(ojPracticeService.selectSubmissionById(submissionId));
    }

    /**
     * 新增OJ代码提交
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submissions:add')")
    @Log(title = "OJ代码提交管理", businessType = BusinessType.INSERT)
    @PostMapping("/submissions")
    public AjaxResult addSubmission(@RequestBody OjSubmission ojSubmission) {
        return toAjax(ojPracticeService.insertSubmission(ojSubmission));
    }

    /**
     * 修改OJ代码提交
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submissions:edit')")
    @Log(title = "OJ代码提交管理", businessType = BusinessType.UPDATE)
    @PutMapping("/submissions")
    public AjaxResult editSubmission(@RequestBody OjSubmission ojSubmission) {
        return toAjax(ojPracticeService.updateSubmission(ojSubmission));
    }

    /**
     * 删除OJ代码提交
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submissions:remove')")
    @Log(title = "OJ代码提交管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/submissions/{submissionIds}")
    public AjaxResult removeSubmissions(@PathVariable String[] submissionIds) {
        return toAjax(ojPracticeService.deleteSubmissionBySubmissionIds(String.join(",", submissionIds)));
    }

    /**
     * 重新评测代码提交
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submissions:edit')")
    @Log(title = "OJ代码重新评测", businessType = BusinessType.UPDATE)
    @PostMapping("/submissions/{submissionId}/rejudge")
    public AjaxResult rejudgeSubmission(@PathVariable String submissionId) {
        // 这里应该调用评测服务重新评测
        // 暂时返回成功
        return success("重新评测已提交");
    }



    /**
     * 获取提交统计
     */
    @PreAuthorize("@ss.hasPermi('system:oj:submissions')")
    @GetMapping("/submissions/stats")
    public AjaxResult getSubmissionStats(String userId, String timeRange)
    {
        try {
            Map<String, Object> stats = ojPracticeService.getSubmissionStats(userId, timeRange);
            return success(stats);
        } catch (Exception e) {
            return error("获取提交统计失败：" + e.getMessage());
        }
    }

    /**
     * 获取编程语言支持列表
     */
    @PreAuthorize("@ss.hasPermi('system:oj:languages')")
    @GetMapping("/languages")
    public AjaxResult getSupportedLanguages()
    {
        try {
            List<Map<String, Object>> languages = ojPracticeService.getSupportedLanguages();
            return success(languages);
        } catch (Exception e) {
            return error("获取语言支持列表失败：" + e.getMessage());
        }
    }

    /**
     * 获取语言配置信息
     */
    @PreAuthorize("@ss.hasPermi('system:oj:languages')")
    @GetMapping("/languages/{language}/config")
    public AjaxResult getLanguageConfig(@PathVariable String language)
    {
        try {
            Map<String, Object> config = ojPracticeService.getLanguageConfig(language);
            return success(config);
        } catch (Exception e) {
            return error("获取语言配置失败：" + e.getMessage());
        }
    }

    /**
     * 获取题目排行榜
     */
    @PreAuthorize("@ss.hasPermi('system:oj:ranking')")
    @GetMapping("/problems/ranking")
    public AjaxResult getProblemRanking(String problemId, String rankingType, Integer limit)
    {
        try {
            List<Map<String, Object>> ranking = ojPracticeService.getProblemRanking(problemId, rankingType, limit);
            return success(ranking);
        } catch (Exception e) {
            return error("获取题目排行榜失败：" + e.getMessage());
        }
    }

    /**
     * 获取用户解题进度
     */
    @PreAuthorize("@ss.hasPermi('system:oj:users')")
    @GetMapping("/users/{userId}/progress")
    public AjaxResult getUserProgress(@PathVariable String userId)
    {
        try {
            Map<String, Object> progress = ojPracticeService.getUserProgress(userId);
            return success(progress);
        } catch (Exception e) {
            return error("获取用户进度失败：" + e.getMessage());
        }
    }

    /**
     * 获取题目分类
     */
    @PreAuthorize("@ss.hasPermi('system:oj:categories')")
    @GetMapping("/categories")
    public AjaxResult getProblemCategories()
    {
        try {
            List<Map<String, Object>> categories = ojPracticeService.getProblemCategories();
            return success(categories);
        } catch (Exception e) {
            return error("获取题目分类失败：" + e.getMessage());
        }
    }

    /**
     * 获取题目标签
     */
    @PreAuthorize("@ss.hasPermi('system:oj:tags')")
    @GetMapping("/tags")
    public AjaxResult getProblemTags()
    {
        try {
            List<Map<String, Object>> tags = ojPracticeService.getProblemTags();
            return success(tags);
        } catch (Exception e) {
            return error("获取题目标签失败：" + e.getMessage());
        }
    }

    /**
     * 获取相关题目推荐
     */
    @PreAuthorize("@ss.hasPermi('system:oj:problems')")
    @GetMapping("/problems/related")
    public AjaxResult getRelatedProblems(String problemId, String userId, Integer limit)
    {
        try {
            List<Map<String, Object>> relatedProblems = ojPracticeService.getRelatedProblems(problemId, userId, limit);
            return success(relatedProblems);
        } catch (Exception e) {
            return error("获取相关题目推荐失败：" + e.getMessage());
        }
    }

    /**
     * 获取题目讨论
     */
    @PreAuthorize("@ss.hasPermi('system:oj:discussions')")
    @GetMapping("/problems/discussions")
    public TableDataInfo getProblemDiscussions(String problemId, Integer pageNum, Integer pageSize)
    {
        startPage();
        List<Map<String, Object>> discussions = ojPracticeService.getProblemDiscussions(problemId);
        return getDataTable(discussions);
    }

    /**
     * 添加题目讨论
     */
    @PreAuthorize("@ss.hasPermi('system:oj:discussions')")
    @PostMapping("/discussions")
    public AjaxResult addProblemDiscussion(@RequestBody Map<String, Object> requestData)
    {
        try {
            String problemId = (String) requestData.get("problemId");
            String title = (String) requestData.get("title");
            String content = (String) requestData.get("content");
            String type = (String) requestData.get("type");
            
            int result = ojPracticeService.addProblemDiscussion(problemId, title, content, type);
            
            return toAjax(result);
        } catch (Exception e) {
            return error("添加讨论失败：" + e.getMessage());
        }
    }

    /**
     * 获取题目解决方案
     */
    @PreAuthorize("@ss.hasPermi('system:oj:solutions')")
    @GetMapping("/problems/solutions")
    public TableDataInfo getProblemSolutions(String problemId, String language, Integer pageNum, Integer pageSize)
    {
        startPage();
        List<Map<String, Object>> solutions = ojPracticeService.getProblemSolutions(problemId, language);
        return getDataTable(solutions);
    }

    /**
     * 获取代码模板
     */
    @PreAuthorize("@ss.hasPermi('system:oj:templates')")
    @GetMapping("/code-templates")
    public AjaxResult getCodeTemplate(String language, String problemType)
    {
        try {
            Map<String, Object> template = ojPracticeService.getCodeTemplate(language, problemType);
            return success(template);
        } catch (Exception e) {
            return error("获取代码模板失败：" + e.getMessage());
        }
    }

    /**
     * 保存用户代码草稿
     */
    @PreAuthorize("@ss.hasPermi('system:oj:drafts')")
    @PostMapping("/code-drafts")
    public AjaxResult saveCodeDraft(@RequestBody Map<String, Object> requestData)
    {
        try {
            String problemId = (String) requestData.get("problemId");
            String code = (String) requestData.get("code");
            String language = (String) requestData.get("language");
            String userId = (String) requestData.get("userId");
            
            int result = ojPracticeService.saveCodeDraft(problemId, code, language, userId);
            
            return toAjax(result);
        } catch (Exception e) {
            return error("保存代码草稿失败：" + e.getMessage());
        }
    }

    /**
     * 获取用户代码草稿
     */
    @PreAuthorize("@ss.hasPermi('system:oj:drafts')")
    @GetMapping("/code-drafts/{problemId}/{userId}")
    public AjaxResult getCodeDraft(@PathVariable String problemId, @PathVariable String userId)
    {
        try {
            Map<String, Object> draft = ojPracticeService.getCodeDraft(problemId, userId);
            return success(draft);
        } catch (Exception e) {
            return error("获取代码草稿失败：" + e.getMessage());
        }
    }

    /**
     * 获取用户代码草稿列表
     */
    @PreAuthorize("@ss.hasPermi('system:oj:drafts')")
    @GetMapping("/code-drafts")
    public TableDataInfo getCodeDraftList(String userId, Integer pageNum, Integer pageSize)
    {
        startPage();
        List<Map<String, Object>> drafts = ojPracticeService.getCodeDraftList(userId);
        return getDataTable(drafts);
    }

    /**
     * 删除代码草稿
     */
    @PreAuthorize("@ss.hasPermi('system:oj:drafts')")
    @DeleteMapping("/code-drafts/{draftId}")
    public AjaxResult deleteCodeDraft(@PathVariable String draftId)
    {
        try {
            int result = ojPracticeService.deleteCodeDraft(draftId);
            return toAjax(result);
        } catch (Exception e) {
            return error("删除代码草稿失败：" + e.getMessage());
        }
    }

    /**
     * 获取OJ系统状态
     */
    @PreAuthorize("@ss.hasPermi('system:oj:status')")
    @GetMapping("/status")
    public AjaxResult getOjSystemStatus()
    {
        try {
            Map<String, Object> status = ojPracticeService.getSystemStatus();
            return success(status);
        } catch (Exception e) {
            return error("获取系统状态失败：" + e.getMessage());
        }
    }

    /**
     * 获取OJ系统配置
     */
    @PreAuthorize("@ss.hasPermi('system:oj:config')")
    @GetMapping("/config")
    public AjaxResult getOjSystemConfig()
    {
        try {
            Map<String, Object> config = ojPracticeService.getSystemConfig();
            return success(config);
        } catch (Exception e) {
            return error("获取系统配置失败：" + e.getMessage());
        }
    }

    /**
     * 获取用户OJ统计信息
     */
    @PreAuthorize("@ss.hasPermi('system:oj:users')")
    @GetMapping("/users/{userId}/stats")
    public AjaxResult getUserOjStats(@PathVariable String userId)
    {
        try {
            Map<String, Object> stats = ojPracticeService.getUserOjStats(userId);
            return success(stats);
        } catch (Exception e) {
            return error("获取用户统计信息失败：" + e.getMessage());
        }
    }

    /**
     * 获取OJ排行榜
     */
    @PreAuthorize("@ss.hasPermi('system:oj:ranking')")
    @GetMapping("/ranking")
    public AjaxResult getOjRanking(String rankingType, String timeRange, Integer limit)
    {
        try {
            List<Map<String, Object>> ranking = ojPracticeService.getOjRanking(rankingType, timeRange, limit);
            return success(ranking);
        } catch (Exception e) {
            return error("获取排行榜失败：" + e.getMessage());
        }
    }

    /**
     * 导出提交记录
     */
    @PreAuthorize("@ss.hasPermi('system:oj:export')")
    @Log(title = "OJ提交记录", businessType = BusinessType.EXPORT)
    @PostMapping("/submissions/export")
    public void exportSubmissions(HttpServletResponse response, String userId, String problemId, 
                                String status, String language, String startTime, String endTime)
    {
        List<OjSubmission> list = ojPracticeService.selectSubmissionList(userId, problemId, status, 
                                                                       language, startTime, endTime);
        ExcelUtil<OjSubmission> util = new ExcelUtil<OjSubmission>(OjSubmission.class);
        util.exportExcel(response, list, "OJ提交记录数据");
    }
} 